import { expect } from '@jest/globals';
import fse from 'fs-extra';
import path from 'path';

import { runHvigorFailAsync } from '../../common/common';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType
} from '../../plugins/project-builder/models/constants';
import { Project } from '../../plugins/project-builder/models/project-models.js';
import { ICaseRecord } from '../../plugins/report-builder/report-models.js';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API11,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility
  }
};

const commonCommand = [
  'clean --mode module -p module=entry@default -p product=default -p requiredDeviceType=phone',
  '--analyze=normal --parallel --incremental --no-daemon'
];

const testfun: TestCaseFun = async (project, taskConfig, record) => {
  // 1. 创建API12 stage 工程
  const entryPath = project.getModule('entry').moduleRootPath();

  await case1(project, record, entryPath);
  await case2(project, record, entryPath);
  await case3(project, record, entryPath);
  await case4(project, record, entryPath);
};

/**
 * 用例1
 * 修改module.json5: module.requestPermissions = [{ "name": "ohos.permission.ACCESS_BLUETOOTH"}]
 */
async function case1(project: Project, record: ICaseRecord, entryPath: string) {
  const entryModuleJson5Path = path.resolve(entryPath, 'src/main/module.json5');
  const moduleJson = fse.readJsonSync(entryModuleJson5Path);
  // 修改
  moduleJson.module.requestPermissions = [
    {
      'name': 'ohos.permission.ACCESS_BLUETOOTH'
    }
  ];
  fse.writeJSONSync(entryModuleJson5Path, moduleJson);

  // 运行
  const commands: string[] = [commonCommand[0], 'assembleHap', commonCommand[1]].join(' ').split(' ');
  const result = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('报错用例1', result);
  expect(result.stderr).toContain('The reason and usedScene attributes are mandatory for user_grant permissions.');
  expect(result.stderr).toContain('* Try the following:');
  expect(result.stderr).toContain('> For the hap module, add the reason and usedScene fields to the permission reported in the preceding file.');
  expect(result.stderr).toContain('> For the har/hsp module, add the reason field to the permission of the error information in the preceding file.');

  // 重置修改
  moduleJson.module.requestPermissions = undefined;
  fse.writeJSONSync(entryModuleJson5Path, moduleJson);
}

/**
 * 用例2
 * 修改color.json: color数组push {
 *     "name": "start.window_background",
 *     "value": "#FFFFFF"
 *   }
 */
async function case2(project: Project, record: ICaseRecord, entryPath: string) {
  const colorJsonPath = path.resolve(entryPath, 'src/main/resources/base/element/color.json');
  const colorJson = fse.readJsonSync(colorJsonPath);
  // 修改
  colorJson.color.push({
    'name': 'start.window_background',
    'value': '#FFFFFF'
  });
  fse.writeJSONSync(colorJsonPath, colorJson);

  // 运行
  const commands: string[] = [commonCommand[0], 'assembleHap', commonCommand[1]].join(' ').split(' ');
  const result = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('报错用例2', result);
  expect(result.stderr).toContain('Error Message: Invalid resource name \'start.window_background\'. It should match the pattern [a-zA-Z0-9_]');
  expect(result.stderr).toContain('* Try the following:');
  expect(result.stderr).toContain('> Modify the name to match the pattern [a-zA-Z0-9_].');

  // 重置修改
  colorJson.color.length = 1;
  fse.writeJSONSync(colorJsonPath, colorJson);
}

/**
 * 用例3
 * 修改color.json: 加个逗号
 */
async function case3(project: Project, record: ICaseRecord, entryPath: string) {
  const colorJsonPath = path.resolve(entryPath, 'src/main/resources/base/element/color.json');
  // 修改
  let colorJson = `{
  "color": [
    {
      "name": "start_window_background",
      "value": "#FFFFFF"
    },
  ]
}`;
  fse.writeFileSync(colorJsonPath, colorJson);

  // 运行
  const commands: string[] = [commonCommand[0], 'assembleHap', commonCommand[1]].join(' ').split(' ');
  const result = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('报错用例3', result);
  expect(result.stderr).toContain('Error Message: Failed to parse the JSON file: incorrect format');
  expect(result.stderr).toContain('* Try the following:');
  expect(result.stderr).toContain('> Check the JSON file and delete unnecessary commas (,).');
  expect(result.stderr).toContain('> Check the JSON file to make sure the root bracket is {}');

  // 重置修改
  colorJson = `{
  "color": [
    {
      "name": "start_window_background",
      "value": "#FFFFFF"
    }
  ]
}`;
  fse.writeFileSync(colorJsonPath, colorJson);
}

/**
 * 用例4
 * 修改module.json5: moduleJson.module.abilities[0].icon = "$media:layered_image1"
 */
async function case4(project: Project, record: ICaseRecord, entryPath: string) {
  const entryModuleJson5Path = path.resolve(entryPath, 'src/main/module.json5');
  const moduleJson = fse.readJsonSync(entryModuleJson5Path);
  // 修改
  moduleJson.module.abilities[0].icon = '$media:layered_image1';
  fse.writeJSONSync(entryModuleJson5Path, moduleJson);

  // 运行
  const commands: string[] = [commonCommand[0], 'assembleHap', commonCommand[1]].join(' ').split(' ');
  const result = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('报错用例4', result);
  expect(result.stderr).toContain('Error Message: The resource reference \'$media:layered_image1\' is not defined.');
  expect(result.stderr).toContain('* Try the following:');
  expect(result.stderr).toContain(' > Check whether this resource is defined anywhere.');

  // 重置修改
  moduleJson.module.abilities[0].icon = '$media:layered_image';
  fse.writeJSONSync(entryModuleJson5Path, moduleJson);
}

TestCaseBuilder.builder()
  .caseName('FORMATED_ERROR_E2E_TEST')
  .description('1. 创建API12 stage 工程；\n' +
    '2. 修改文件内容\n' +
    '3. 运行报错\n' +
    '4. 重置修改\n' +
    '5. 重复步骤2、3、4，一次重复就是一个用例，总共四个\n'
  )
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testfun)
  .load();
